package com.vinoxm.rss.redis;

import com.vinoxm.rss.dao.RssDao;
import com.vinoxm.rss.model.RssResult;
import com.vinoxm.rss.subscribe.SubscribeAdapter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.annotation.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
@Aspect
@Log4j2
public class RedisControlAop {

    @Setter(onMethod_ = {@Resource})
    private RssDao rssDao;

    @Setter(onMethod_ = @Resource)
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Setter(onMethod_ = @Resource)
    private TransactionDefinition transactionDefinition;

    @Setter(onMethod_ = @Resource)
    private SubscribeAdapter subscribeAdapter;

    private TransactionStatus transactionStatus;

    @Pointcut("@annotation(com.vinoxm.rss.redis.annotation.RssUpdating)")
    public void setRssUpdating(){}

    @Before("setRssUpdating()")
    public void beforeRssUpdating() {
        log.info("[Rss subscribe] Starting!");
        RedisClient.setRssUpdating(true);
        transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
    }

    @AfterThrowing("setRssUpdating()")
    public void afterTrowingRssUpdating() {
        dataSourceTransactionManager.rollback(transactionStatus);
        RedisClient.setRssUpdating(false);
    }

    @AfterReturning("setRssUpdating()")
    public void afterReturningRssUpdating() {
        List<RssResult> list = subscribeAdapter.getResultListAndRemove();
        if (null != list) {
            List<Long> ids = list.stream().map(RssResult::getId).filter(Objects::nonNull).collect(Collectors.toList());
            if (ids.size() > 0) {
                List<String> seasons = rssDao.selectSeasonByResultIds(ids);
                if (seasons.size() > 0) RedisClient.removeRssSubsBySeason(seasons);
            }
        }
        dataSourceTransactionManager.commit(transactionStatus);
        RedisClient.setRssUpdating(false);
        log.info("[Rss subscribe] Finish!");
    }
}
